package repository

import (
	"blog_go/internal/model"
	"blog_go/pkg/common/constant"
	"blog_go/pkg/common/fileoper"
	regexpattern "blog_go/pkg/common/regexppattern"
	"blog_go/pkg/helper/md5"
	"regexp"
	"time"

	"errors"
	"mime/multipart"
)

type UserRepository interface {
	QueryFollowUser(userId int) ([]*model.UserView, error)
	QueryAllUser() ([]*model.UserView, error)
	QueryUser(userId int, targetUserId int) (*model.UserView, error)
	FollowUser(userId int, followerId int) error
	UnFollowUser(userId int, followerId int) error
	UpdateUserProfile(user model.User, files *multipart.Form) (*model.UserView, error)
	UpdatePwd(user model.UserPwd) error
	UpdateUserStatus(userId int, status int) error
	ResetUserPwd(userId int) error
	RegisterUser(user model.User) error
	LoginUser(loginUser model.LoginUser) (*model.UserView, error)
	LoginAdmin(loginUser model.LoginUser) (*model.Admin, error)
	DelUser(userId int) error
	RefreshToken(userId int) (*model.User, error)
}
type userRepository struct {
	*BaseRepository
}

func NewUserRepository(repository *BaseRepository) UserRepository {
	return &userRepository{
		BaseRepository: repository,
	}
}

// 关注用户
func (r *userRepository) FollowUser(userId int, followerId int) error {
	tx, err := r.db.Begin()
	if err != nil {
		return err
	}

	defer func() {
		if err != nil {
			tx.Rollback()
		}
	}()

	var count int
	err = tx.QueryRow(`
		SELECT 
			count(*) 
		FROM 
			user_follow 
		WHERE 
			user_id = ? 
		AND follower_id = ?`, userId, followerId).Scan(&count)
	if err != nil {
		return err
	}

	if count > 0 {
		return errors.New("该用户已关注")
	}

	_, err = tx.Exec(`
		INSERT INTO user_follow
		(
			user_id, 
			follower_id
		) 
		VALUES(?, ?)`, userId, followerId)
	if err != nil {
		return err
	}

	//用户的关注数+1
	_, err = tx.Exec(`
		UPDATE 
			user 
		SET 
			follow = follow + 1 
		WHERE 
			user_id = ?`, userId)
	if err != nil {
		return err
	}

	_, err = tx.Exec(`
		UPDATE 
			user 
		SET 
			followed = followed + 1 
		WHERE 
			user_id = ?`, followerId)
	if err != nil {
		return err
	}

	err = tx.Commit()
	return err
}

// 取消关注用户
func (r *userRepository) UnFollowUser(userId int, followerId int) error {
	tx, err := r.db.Begin()
	if err != nil {
		return err
	}

	defer func() {
		if err != nil {
			tx.Rollback()
		}
	}()

	var count int
	err = tx.QueryRow(`
		SELECT 
			count(*) 
		FROM 
			user_follow 
		WHERE 
			user_id = ? 
		AND follower_id = ?`, userId, followerId).Scan(&count)
	if err != nil {
		return err
	}

	if count == 0 {
		return errors.New("该用户已取消关注")
	}

	_, err = tx.Exec(`
		DELETE FROM user_follow 
		WHERE 
			user_id = ? 
		AND follower_id = ?`, userId, followerId)
	if err != nil {
		return err
	}

	_, err = tx.Exec(`
		UPDATE 
			user 
		SET 
			followed = followed - 1 
		WHERE 
			user_id = ?`, followerId)
	if err != nil {
		return err
	}

	_, err = tx.Exec(`
		UPDATE 
			user 
		SET 
			follow = follow - 1 
		WHERE 
			user_id = ?`, userId)
	if err != nil {
		return err
	}

	err = tx.Commit()
	return err
}

// 查看关注用户
func (r *userRepository) QueryFollowUser(userId int) ([]*model.UserView, error) {
	followers := make([]*model.UserView, 0) // 被关注用户信息

	query := `
		SELECT 
			u.user_id, 
			u.display_name, 
			COALESCE(u.signature, '') 'signature', 
			COALESCE(u.real_name, '') 'realName', 
			u.img_file_id, u.follow, 
			u.followed, 
			COALESCE(u.school, '') 'school', 
			u.user_type,
			COALESCE(u.college, '') 'college', 
			COALESCE(u.class, '') 'class', 
			u.status, 
			u.create_time, 
			COALESCE(f.file_name, '') 'fileName', 
			COALESCE(f.file_path, '') 'filePath'
		FROM 
			user_follow uf 
		JOIN 
			user u 
		ON 
			uf.follower_id = u.user_id
		LEFT JOIN 
			fileinfo f 
		ON 
			u.img_file_id = f.file_id
		WHERE 
			uf.user_id = ?`

	rows, err := r.db.Query(query, userId)
	if err != nil {
		return nil, err
	}

	defer rows.Close()

	for rows.Next() {
		var follower model.UserView
		err := rows.Scan(&follower.UserId, &follower.DisplayName, &follower.Signature, &follower.RealName,
			&follower.ImgFileId, &follower.Follow, &follower.Followed, &follower.School, &follower.UserType,
			&follower.College, &follower.Class, &follower.Status, &follower.CreateTime,
			&follower.ImgFileName, &follower.ImgFilePath,
		)
		if err != nil {
			return nil, err
		}

		follower.IsFollowed = true
		followers = append(followers, &follower)
	}

	return followers, nil
}

// 获取他人信息
func (r *userRepository) QueryUser(userId int, targetUserId int) (*model.UserView, error) {
	user := new(model.UserView)
	var count int

	err := r.db.QueryRow(`
		SELECT 
			COUNT(*) 
		FROM 
			user 
		WHERE 
			user_id = ?`, targetUserId).Scan(&count)
	if err != nil {
		return nil, err
	}

	if count == 0 {
		return nil, errors.New("当前用户不存在")
	}

	query := `
		SELECT 
			user_id, 
			display_name, 
			COALESCE(signature, '') 'signature', 
			COALESCE(real_name, '') 'realName', 
			img_file_id, 
			follow, 
			followed,
			COALESCE(school, '') 'school', 
			COALESCE(college, '') 'college', 
			COALESCE(class,'') 'class', 
			status, 
			user_type, 
			create_time, 
			COALESCE(file_name, '') 'fileName', 
			COALESCE(file_path, '') 'filePath',
		CASE WHEN EXISTS (SELECT 1 FROM user_follow uf WHERE follower_id = user.user_id AND uf.user_id = ?) THEN 'true' ELSE 'false' END as is_follow
		FROM 
			user 
		LEFT JOIN 
			fileinfo 
		ON 
			img_file_id = file_id 
		WHERE 
			user_id = ?`

	err = r.db.QueryRow(query, userId, targetUserId).Scan(
		&user.UserId, &user.DisplayName, &user.Signature, &user.RealName, &user.ImgFileId, &user.Follow,
		&user.Followed, &user.School, &user.College, &user.Class, &user.Status, &user.UserType, &user.CreateTime, &user.ImgFileName, &user.ImgFilePath, &user.IsFollowed)
	if err != nil {
		return nil, err
	}

	return user, nil
}

// 管理员获取全部用户信息
func (r *userRepository) QueryAllUser() ([]*model.UserView, error) {
	users := make([]*model.UserView, 0)

	query := `
		SELECT 
			user_id, 
			account, 
			display_name, 
			COALESCE(signature, '') 'signature', 
			COALESCE(real_name, '') 'realName', 
			img_file_id, 
			follow, 
			followed,
			COALESCE(school, '') 'school', 
			COALESCE(college, '') 'college', 
			COALESCE(class,'') 'class', 
			status, 
			user_type, 
			create_time, 
			COALESCE(file_name, '') 'fileName', 
			COALESCE(file_path, '') 'filePath'
		FROM 
			user 
		LEFT JOIN 
			fileinfo 
		ON 
			img_file_id = file_id`

	rows, err := r.db.Query(query)
	if err != nil {
		return nil, err
	}

	defer rows.Close()

	for rows.Next() {
		var user model.UserView

		err := rows.Scan(&user.UserId, &user.Account, &user.DisplayName, &user.Signature, &user.RealName, &user.ImgFileId, &user.Follow,
			&user.Followed, &user.School, &user.College, &user.Class, &user.Status, &user.UserType, &user.CreateTime, &user.ImgFileName, &user.ImgFilePath)
		if err != nil {
			return nil, err
		}

		users = append(users, &user)
	}

	return users, nil
}

// 更新用户资料
func (r *userRepository) UpdateUserProfile(user model.User, files *multipart.Form) (*model.UserView, error) {
	tx, err := r.db.Begin()
	if err != nil {
		return nil, err
	}

	defer func() {
		if err != nil {
			tx.Rollback()
		}
	}()

	tempUser := new(model.User)

	//查询用户是否有头像
	err = tx.QueryRow(`
		SELECT 
			img_file_id 
		FROM 
			user 
		WHERE 
			user_id = ?`, user.UserId).Scan(&tempUser.ImgFileId)
	if err != nil {
		return nil, err
	}

	//修改图片
	fileId, err := fileoper.EditCover(tx, files, "用户个人头像", tempUser.ImgFileId, fileoper.AvatarImgPath)
	if err != nil {
		return nil, err
	}

	//更新用户资料
	_, err = tx.Exec(`
		UPDATE 
			user 
		SET 
			display_name = ?, 
			signature = ?, 
			real_name = ?, 
			school = ?, 
			college = ?, 
			class = ?, 
			img_file_id = ? 
		WHERE 
			user_id = ?`,
		user.DisplayName, user.Signature, user.RealName, user.School, user.College, user.Class, fileId, user.UserId)
	if err != nil {
		return nil, err
	}

	query := `
		SELECT 
			user_id, 
			account, 
			password, 
			display_name, 
			COALESCE(signature, '') 'signature', 
			COALESCE(real_name, '') 'realName', 
			img_file_id, 
			follow, 
			followed, 
			COALESCE(school, '') 'school',
			COALESCE(college, '') 'college', 
			COALESCE(class, '') 'class', 
			status, 
			user_type, 
			create_time, 
			COALESCE(file_name, '') 'fileName', 
			COALESCE(file_path, '') 'filePath'
		FROM 
			user 
		LEFT JOIN 
			fileinfo 
		ON 
			img_file_id = file_id 
		WHERE 
			user_id = ?`

	userResult := new(model.UserView)

	err = tx.QueryRow(query, user.UserId).Scan(&userResult.UserId, &userResult.Account, &userResult.Password, &userResult.DisplayName,
		&userResult.Signature, &userResult.RealName, &userResult.ImgFileId, &userResult.Follow,
		&userResult.Followed, &userResult.School, &userResult.College, &userResult.Class, &userResult.Status,
		&userResult.UserType, &userResult.CreateTime, &userResult.ImgFileName, &userResult.ImgFilePath)

	if err != nil {
		return nil, err
	}

	err = tx.Commit()
	return userResult, err
}

// 修改用户状态
func (r *userRepository) UpdateUserStatus(userId int, status int) error {
	_, err := r.db.Exec(`
		UPDATE 
			user 
		SET 
			status = ? 
		WHERE 
			user_id = ?`, status, userId)
	if err != nil {
		return err
	}

	return nil
}

// 修改用户、管理员密码
func (r *userRepository) UpdatePwd(user model.UserPwd) error {
	matched, err := regexp.MatchString(regexpattern.PasswordRegex, user.NewPassword)
	if err != nil {
		return err
	}

	if !matched {
		return errors.New("密码格式错误,仅允许出现大小写英文字母、数字和!#$%&*+/=?^_`{|}~-.特殊字符!密码长度必须在6-18之间")
	}

	var count int
	pwd := md5.Md5(user.Password)

	query := ""
	if user.UserType == 1 { //用户
		query = `
			SELECT 
				COUNT(*) 
			FROM 
				user 
			WHERE 
				user_id = ? 
			AND password = ?`
	} else if user.UserType == 0 {
		query = `
			SELECT 
				COUNT(*) 
			FROM 
				admin 
			WHERE 
				admin_id = ? 
			AND password = ?`
	}

	err = r.db.QueryRow(query, user.UserId, pwd).Scan(&count)
	if err != nil {
		return err
	}

	if count == 0 {
		return errors.New("旧密码错误")
	}

	newPwd := md5.Md5(user.NewPassword)

	if user.UserType == 1 {
		_, err = r.db.Exec(`
			UPDATE 
				user 
			SET 
				password = ? 
			WHERE 
				user_id = ?`, newPwd, user.UserId)
	} else if user.UserType == 0 {
		_, err = r.db.Exec(`
			UPDATE 
				admin 
			SET 
				password = ? 
			WHERE 
				admin_id = ?`, newPwd, user.UserId)
	}

	if err != nil {
		return err
	}

	return nil
}

// 重置用户密码
func (r *userRepository) ResetUserPwd(userId int) error {
	newPwd := md5.Md5(constant.DefaultPassWord)

	_, err := r.db.Exec(`
		UPDATE 
			user 
		SET 
			password = ? 
		WHERE 
			user_id = ?`, newPwd, userId)
	if err != nil {
		return err
	}

	return nil
}

// 用户登录
func (r *userRepository) LoginUser(loginUser model.LoginUser) (*model.UserView, error) {
	user := new(model.UserView)
	newPwd := md5.Md5(loginUser.Password)
	var id int

	err := r.db.QueryRow(`
		SELECT 
			user_id 
		FROM 
			user 
		WHERE 
			account = ? 
		AND password = ?`, loginUser.Account, newPwd).Scan(&id)
	if id == 0 {
		return nil, nil
	}
	if err != nil {
		return nil, err
	}

	query := `
		SELECT 
			user_id, 
			account, 
			display_name, 
			COALESCE(signature, '') 'signature', 
			COALESCE(real_name, '') 'realName', 
			img_file_id, 
			follow, 
			followed, 
			COALESCE(school, '') 'school', 
			COALESCE(college, '') 'college', 
			COALESCE(class, '') 'class', 
			status, 
			user_type, 
			create_time, 
			COALESCE(file_name, '') 'fileName', 
			COALESCE(file_path, '') 'filePath'
		FROM 
			user 
		LEFT JOIN 
			fileinfo 
		ON 
			img_file_id = file_id 
		WHERE 
			user_id = ?`

	err = r.db.QueryRow(query, id).Scan(&user.UserId, &user.Account, &user.DisplayName,
		&user.Signature, &user.RealName, &user.ImgFileId, &user.Follow,
		&user.Followed, &user.School, &user.College, &user.Class, &user.Status,
		&user.UserType, &user.CreateTime, &user.ImgFileName, &user.ImgFilePath)
	if err != nil {
		return nil, err
	}

	if user.Status == 2 {
		return nil, errors.New("等待管理员审核账户")
	}

	if user.Status == 3 {
		return nil, errors.New("账户未通过审核")
	}

	return user, nil
}

// 管理员登录
func (r *userRepository) LoginAdmin(loginUser model.LoginUser) (*model.Admin, error) {
	admin := new(model.Admin)
	newPwd := md5.Md5(loginUser.Password)

	query := `
		SELECT 
			admin_id, 
			COALESCE(real_name, '') 'realName', 
			account, 
			user_type, 
			COALESCE(school, '') 'school', 
			COALESCE(college, '') 'college', 
			COALESCE(class, '') 'class' 
		FROM
			admin
		WHERE 
			account = ? 
		AND password = ?`

	err := r.db.QueryRow(query, loginUser.Account, newPwd).
		Scan(&admin.AdminId, &admin.RealName, &admin.Account, &admin.UserType, &admin.School, &admin.College, &admin.Class)

	if admin.AdminId == 0 {
		return nil, nil // 表示没有查询到数据 登陆密码错误
	}
	if err != nil {
		return nil, err
	}

	return admin, nil
}

// 用户注册
func (r *userRepository) RegisterUser(user model.User) error {
	matched, err := regexp.MatchString(regexpattern.AccountRegex, user.Password)

	if err != nil {
		return err
	}

	if !matched {
		return errors.New("账户格式错误,账号只能包含字母和数字账号长度必须在5-15之间")
	}

	matched, err = regexp.MatchString(regexpattern.PasswordRegex, user.Password)
	if err != nil {
		return err
	}

	if !matched {
		return errors.New("密码格式错误,仅允许出现A~Z, a~z, 0~9和!#$%&*+/=?^_`{|}~-.特殊字符!密码长度必须在6-18之间")
	}

	//查询是否有同样账户
	var count int

	tx, err := r.db.Begin()
	if err != nil {
		return err
	}

	defer func() {
		if err != nil {
			tx.Rollback()
		}
	}()

	err = tx.QueryRow(`
		SELECT 
			COUNT(*) 
		FROM 
			user 
		WHERE 
			account = ?`, user.Account).Scan(&count)
	if err != nil {
		tx.Rollback()
		return err
	}

	if count > 0 {
		return errors.New("账户重复")
	}

	//初始化用户信息
	newPwd := md5.Md5(user.Password)
	user.CreateTime = time.Now().Format("2006-01-02 15:04:05")
	user.Follow = 0
	user.Followed = 0
	user.Status = 2
	user.UserType = 1
	user.ImgFileId = 0

	ret, err := tx.Exec(`
		INSERT INTO user
		(
			account, 
			password, 
			display_name, 
			img_file_id, 
			follow, 
			followed, 
			status, 
			user_type, 
			create_time
		) 
		values(?, ?, ?, ?, ?, ?, ?, ?, ?)`, user.Account, newPwd, user.DisplayName, user.ImgFileId, user.Follow, user.Followed, user.Status, user.UserType, user.CreateTime)
	if err != nil {
		return err
	}

	//创建默认收藏夹
	userId, err := ret.LastInsertId()
	if err != nil {
		return err
	}

	_, err = tx.Exec(`
		INSERT INTO collection
		(
			user_id, 
			collection_name
		) 
		VALUES(?, ?)`, userId, "默认收藏夹")
	if err != nil {
		return err
	}

	err = tx.Commit()
	return err
}

// 删除用户
func (r *userRepository) DelUser(userId int) error {
	var status int
	err := r.db.QueryRow(`
		SELECT 
			COUNT(*) 
		FROM 
			user 
		WHERE 
			user_id = ?`, userId).Scan(&status)
	if err != nil {
		return err
	}

	if status == 3 {
		return errors.New("只能删除审核不通过用户")
	}

	_, err = r.db.Exec(`
		DELETE FROM user 
		WHERE 
			user_id = ?`, userId)
	if err != nil {
		return err
	}

	return nil
}

func (r *userRepository) RefreshToken(userId int) (*model.User, error) {
	user := new(model.User)

	query := `
		SELECT 
			user_id, 
			account, 
			status, 
			user_type
		FROM 
			user 
		WHERE 
			user_id = ?`

	rows, err := r.db.Query(query, userId)
	if err != nil {
		return nil, err
	}

	defer rows.Close()

	for rows.Next() {
		err = rows.Scan(&user.UserId, &user.Account, &user.Status, &user.UserType)
		if err != nil {
			return nil, err
		}
	}

	return user, nil
}
